package org.dreamwork.seagragon;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.OutputStream;

/**
 * SeaDragon 运行时环境
 *
 * <p>Runtime 模拟了一个 Http 请求的环境，提供且仅提供了模拟 GET 方法请求一个服务器端资源</p>
 *
 * <pre>Created by IntelliJ IDEA.
 * User: seth
 * Date: 2010-4-24
 * Time: 18:02:26</pre>
 */
public class Runtime {
    private ServletContext context;

    private static Runtime runtime;

    private Runtime (ServletContext context) {
        this.context = context;
    }

    /**
     * 根据 ServletContext 实例获取一个运行期环境实例
     * @param context ServleContext
     * @return 运行期环境
     */
    public static Runtime getRuntime (ServletContext context) {
        if (runtime == null)
            runtime = new Runtime (context);
        return runtime;
    }

    /**
     * 执行一个 GET 请求
     *
     * <p>模拟一个指定 URL 的基于 GET 方法的服务器资源请求，并将返回结果输出到 out 中</p>
     * <i><strong>注意</strong>: 该方法是异步执行的</i>
     *
     * @param url 指定的url
     * @param out 结果输出流
     * @see #executeWebPage(String, java.io.OutputStream, String)
     */
    public void executeWebPage (String url, OutputStream out) {
        new WebPageWorker (context, out, url, null).start ();
    }

    /**
     * 执行一个 GET 请求
     *
     * <p>模拟一个指定 URL 的基于 GET 方法的服务器资源请求，并将返回结果输出到 out 中</p>
     * 和{@link #executeWebPage(String, java.io.OutputStream)} 不一样，该方法总是启用 Http 会话模拟
     * <i><strong>注意</strong>: 该方法是同步执行的，这意味着客户应用程序必须等待服务器端资源完成处理</i>
     *
     * @param url 指定的url
     * @param out 结果输出流
     * @param sessionId 指定的HTTP会话ID。若该值为 null，则请求将产生一个新的会话，否则使用 sessionId 指定的会话。
     * @return Http会话的ID
     */
    public String executeWebPage (String url, OutputStream out, String sessionId) {
        WebPageWorker worker = new WebPageWorker (context, out, url, sessionId);
        worker.run ();
        return worker.getSessionId ();
    }

    /**
     * 创建一个客户-服务端共享的 HttpSession 对象。
     * @return HttpSession实例
     * @see #getHttpSession()
     */
    public HttpSession createHttpSession () {
        ImitationHttpRequest request = new ImitationHttpRequest (context, "/", null);
        return request.getSession (true);
    }

    /**
     * 获取当前客户-服务端共享的 HttpSession 对象（若存在）
     * <p>若当前无共享的 HttpSession 对象，则返回 null。可以通过 {@link #createHttpSession()} 来创建一个共享的 HttpSession
     * @return HttpSession 实例。
     * @see #createHttpSession()
     */
    public HttpSession getHttpSession () {
        ImitationHttpRequest request = new ImitationHttpRequest (context, "/", null);
        return request.getSession ();        
    }
}